package pers.cz.jefconfig.config;

import pers.cz.jefconfig.ext.JefLinkedHashMap;
import pers.cz.jefconfig.io.IOUtils;
import pers.cz.jefconfig.log.LogUtils;
import pers.cz.jefconfig.reader.FileType;
import pers.cz.jefconfig.resource.FileResource;
import pers.cz.jefconfig.resource.ResourceUtil;
import pers.cz.jefconfig.tools.StringUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.net.URL;
import java.util.List;
import java.util.Map;

/**
 * @program: PostGirl-panent
 * @description: 通用配置管理器
 * @author: Cheng Zhi
 * @create: 2022-06-28 10:29
 **/
public class Configuration extends Cfg {

    private static final int MAX_ENTRIES=100; // 缓存最大存储量，如果超过这个将会发生新的覆盖老的，LRU算法。

    private Map<String,Object> cache;

    private String fileName;

    private static File file;

    /**
     * 用来区分文件类型，不同的文件后面解析的时候要使用不同的策略
     */
    private static FileType fileType;

    public Configuration(String fileName) {
        // 初始化一个缓存，缓存大小设置为100
        cache = new JefLinkedHashMap<String,Object>(){
            private static final long serialVersionUID = 1L;
            // 删除最老的值
            protected boolean removeEldestEntry(Map.Entry<String, Object> eldest) {
                return size()>MAX_ENTRIES;
            }
        };
        this.fileName = fileName;
    }

    /**
     * 通过键值获取value值，可指定默认值（先从系统变量中获取，如果系统变量中没有，则从配置文件中获取）
     * @param itemKey
     * @param defaultKeyValue
     * @return
     */
    @Override
    protected Object get(String itemKey, String defaultKeyValue) {

        // 这里要做一次转换，传入的是CLENT_HOST,要转换为client.host
        String key = StringUtils.replaceChars(itemKey, "_$", ".-").toLowerCase();
        // 先从系统变量中获取
        Object value = System.getProperty(key);
        if (value != null) {
            return value;
        }
        try {
            // 如果缓存中没有，加入到缓存
            if (!cache.containsKey(key)) {

                if (file == null) {
                    getFile();
                }
                // 缓存中没有先去文件中加载，这个参考spring的实现方式
                String filePath = file.getPath();
                String fileName = file.getName();
                if (fileName.endsWith(".properties")) {
                    fileType = FileType.PROPERTIES;
                } else if (fileName.endsWith(".yaml") || fileName.endsWith(".yml") ) {
                    fileType = FileType.YMAL;
                } else if (fileName.endsWith(".xml")) {
                    fileType = FileType.XML;
                } else {
                    throw new FileNotFoundException(fileName + "文件暂不支持处理！！！");
                }
                FileInputStream fileInputStream = new FileInputStream(filePath);
                Map<String, Object> propertiesMap = IOUtils.loadProperties(fileInputStream,fileType);
                cache.putAll(propertiesMap);

            }
            value = cache.get(key);
            return  value == null ? defaultKeyValue : value;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return defaultKeyValue;
    }

    @Override
    protected void set(String itemKey, Object value) {
        // 这里要做一次转换，传入的是CLENT_HOST,要转换为client.host
        String key = StringUtils.replaceChars(itemKey, "_$", ".-").toLowerCase();
        cache.put(key, value);
    }

    private void getFile() {

        List<URL> urls = ResourceUtil.getResources(fileName);
        // 获取协议
        file = FileResource.getFileResource(urls.get(0)).getFile();

        LogUtils.info("JEF is using config file:" + (null == file ? "Default" : file.getAbsolutePath()));
    }

    public Map<String, Object> getAllCache() {
        return cache;
    }
}
